package com.yykj.backstage.all.service.impl;

import com.yykj.backstage.all.dto.TouSuCreateDTO;
import com.yykj.backstage.all.dto.TouSuFixDTO;
import com.yykj.backstage.all.dto.TouSuSearchDTO;
import com.yykj.backstage.all.model.entity.TouSu;
import com.yykj.backstage.all.model.entity.TouSuType;
import com.yykj.backstage.all.model.repository.TouSuRepository;
import com.yykj.backstage.all.model.repository.TouSuTypeRepository;
import com.yykj.backstage.all.service.TouSuService;
import com.yykj.common.enums.ResultEnums;
import com.yykj.common.exception.NormalException;
import com.yykj.common.util.LocalDateTimeFormatterUtil;
import com.yykj.common.util.LocalStringUtil;
import com.yykj.common.util.PageRequestUtil;
import com.yykj.common.vo.PageData;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class TouSuServiceImpl implements TouSuService {

    @Override
    public TouSuType editTouSuType(TouSuType type) {
        return typeRepository.save(type);
    }

    @Override
    public void deleteTouSuType(Integer id) {
        TouSuType touSuType = typeRepository.findById(id).orElseThrow(() -> new NormalException(ResultEnums.NOT_EXIST));
        typeRepository.delete(touSuType);
    }

    @Override
    public List<TouSuType> listTouSuType() {
        return typeRepository.findAllByOrderBySorting();
    }

    @Override
    public TouSu createTouSu(TouSuCreateDTO touSuCreateDTO) {
        TouSu ts = new TouSu();
        BeanUtils.copyProperties(touSuCreateDTO,ts);
        return touSuRepository.save(ts);
    }

    @Override
    public PageData<TouSu> listTouSu(TouSuSearchDTO touSuSearchDTO) {
        PageRequest pageRequest = PageRequest.of(
                PageRequestUtil.getPage(touSuSearchDTO.getCurrentPage()),
                PageRequestUtil.getSize(touSuSearchDTO.getPageSize()),
                Sort.by(Sort.Order.desc("addTime"))
        );
        Page<TouSu> list = touSuRepository.findAll(generateSpecification(touSuSearchDTO), pageRequest);
        return PageData.formatList(list, PageRequestUtil.getPage(touSuSearchDTO.getCurrentPage()),
                PageRequestUtil.getSize(touSuSearchDTO.getPageSize()));
    }

    private Specification<TouSu> generateSpecification(TouSuSearchDTO searchDTO) {
        return new Specification<TouSu>() {
            @Override
            public Predicate toPredicate(Root<TouSu> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicateList = new ArrayList<>();
                if (searchDTO.getTypeId() != null && searchDTO.getTypeId() > 0) {
                    predicateList.add(builder.equal(root.get("typeId"), searchDTO.getTypeId()));
                }
                if (!StringUtils.isEmpty(searchDTO.getTypeName())) {
                    predicateList.add(builder.like(root.get("typeName"),
                            LocalStringUtil.getLikeString(searchDTO.getTypeName())));
                }

                if (searchDTO.getStatus() != null) {
                    predicateList.add(builder.equal(root.get("status"), searchDTO.getStatus()));
                }

                if (!StringUtils.isEmpty(searchDTO.getStartTime())) {
                    LocalDateTime startTime = LocalDateTime.of(
                            LocalDate.parse(searchDTO.getStartTime(), LocalDateTimeFormatterUtil.getLocalDateFormatter())
                            , LocalTime.MIN
                    );
                    predicateList.add(builder.greaterThanOrEqualTo(root.get("addTime"), startTime));

                }

                if (!StringUtils.isEmpty(searchDTO.getEndTime())) {
                    LocalDateTime endTime = LocalDateTime.of(
                            LocalDate.parse(searchDTO.getEndTime(), LocalDateTimeFormatterUtil.getLocalDateFormatter())
                            , LocalTime.MIN
                    );
                    predicateList.add(builder.lessThanOrEqualTo(root.get("addTime"), endTime));
                }

                Predicate[] predicates = new Predicate[predicateList.size()];
                return query.where(predicateList.toArray(predicates)).getRestriction();
            }
        };
    }

    @Override
    public void fixTouSu(TouSuFixDTO fixDTO) {
        TouSu touSu = touSuRepository.findById(fixDTO.getId()).orElseThrow(() -> new NormalException(ResultEnums.NOT_EXIST));
        touSu.setFixTime(LocalDateTime.now());
        touSu.setStatus(1);
        touSu.setRemark(fixDTO.getRemark());
        touSuRepository.save(touSu);
    }


    private TouSuTypeRepository typeRepository;

    private TouSuRepository touSuRepository;

    @Autowired
    public void setTypeRepository(TouSuTypeRepository typeRepository) {
        this.typeRepository = typeRepository;
    }

    @Autowired
    public void setTouSuRepository(TouSuRepository touSuRepository) {
        this.touSuRepository = touSuRepository;
    }
}
